#!/usr/bin/env python3
"""
COS CLI Installation Script
Supports system-wide and user-level installation/uninstallation
"""

import argparse
import os
import sys
import shutil
import platform
from pathlib import Path


class Colors:
    """ANSI color codes"""

    GREEN = "\033[92m"
    YELLOW = "\033[93m"
    RED = "\033[91m"
    BLUE = "\033[94m"
    RESET = "\033[0m"
    BOLD = "\033[1m"


def print_success(msg):
    print(f"{Colors.GREEN}✓{Colors.RESET} {msg}")


def print_error(msg):
    print(f"{Colors.RED}✗{Colors.RESET} {msg}")


def print_warning(msg):
    print(f"{Colors.YELLOW}⚠{Colors.RESET} {msg}")


def print_info(msg):
    print(f"{Colors.BLUE}ℹ{Colors.RESET} {msg}")


class Installer:
    def __init__(self, system_mode=False, install_cli=True, install_gui=False):
        self.system_mode = system_mode
        self.install_cli = install_cli
        self.install_gui = install_gui
        self.cli_name = "cos"
        self.gui_name = "cos-gui"
        self.repo_root = Path(__file__).parent.parent.resolve()
        self.cli_path = self.repo_root / "bin" / self.cli_name
        self.gui_path = self.repo_root / "bin" / self.gui_name

        # Set installation paths based on mode and platform
        if system_mode:
            if platform.system() == "Windows":
                self.install_dir = (
                    Path(os.environ.get("ProgramFiles", "C:\\Program Files")) / "cos"
                )
            else:
                self.install_dir = Path("/usr/local/bin")
                self.config_dir = Path("/usr/local/etc/cos")
        else:
            home = Path.home()
            if platform.system() == "Windows":
                self.install_dir = home / "AppData" / "Local" / "cos" / "bin"
            else:
                self.install_dir = home / ".local"/ "bin"
                self.config_dir = home / ".config" / "cos"

        # Set binary paths
        self.installed_cli = self.install_dir / self.cli_name
        self.installed_gui = self.install_dir / self.gui_name

        if platform.system() == "Windows":
            self.installed_cli = self.installed_cli.with_suffix(".exe")
            self.installed_gui = self.installed_gui.with_suffix(".exe")
            self.cli_path = self.cli_path.with_suffix(".exe")
            self.gui_path = self.gui_path.with_suffix(".exe")

    def check_permissions(self):
        """Check if we have write permissions to the installation directory"""
        if self.system_mode and platform.system() != "Windows":
            if os.geteuid() != 0:
                print_error("System installation requires root privileges")
                print_info("Please run with sudo: sudo just install")
                return False
        return True

    def ensure_binaries_exist(self):
        """Check if the required binaries exist"""
        if self.install_cli and not self.cli_path.exists():
            print_error(f"CLI binary not found: {self.cli_path}")
            print_info("Please build the CLI first: just build-cli")
            return False

        if self.install_gui and not self.gui_path.exists():
            print_error(f"GUI binary not found: {self.gui_path}")
            print_info("Please build the GUI first: just build-gui")
            return False

        return True

    def install(self):
        """Install the binaries"""
        targets = []
        if self.install_cli:
            targets.append("CLI")
        if self.install_gui:
            targets.append("GUI")

        print(f"\n{Colors.BOLD}Installing COS {' and '.join(targets)}...{Colors.RESET}")
        print(f"Mode: {'System' if self.system_mode else 'User'}")
        print(f"Target: {self.install_dir}\n")

        if not self.check_permissions():
            return False

        if not self.ensure_binaries_exist():
            return False

        # Create installation directory
        try:
            self.install_dir.mkdir(parents=True, exist_ok=True)
        except PermissionError:
            print_error(f"Permission denied: Cannot create {self.install_dir}")
            return False

        # Install CLI
        if self.install_cli:
            try:
                shutil.copy2(self.cli_path, self.installed_cli)
                self.installed_cli.chmod(0o755)
                print_success(f"Installed CLI to: {self.installed_cli}")
            except Exception as e:
                print_error(f"Failed to copy CLI binary: {e}")
                return False

        # Install GUI
        if self.install_gui:
            try:
                shutil.copy2(self.gui_path, self.installed_gui)
                self.installed_gui.chmod(0o755)
                print_success(f"Installed GUI to: {self.installed_gui}")
            except Exception as e:
                print_error(f"Failed to copy GUI binary: {e}")
                return False

            # Create desktop shortcuts for GUI (Linux only)
            if platform.system() == "Linux" and not self.system_mode:
                self._create_desktop_entry()

        # Create config directory (Unix only)
        if platform.system() != "Windows" and hasattr(self, "config_dir"):
            try:
                self.config_dir.mkdir(parents=True, exist_ok=True)
                print_success(f"Created config directory: {self.config_dir}")
            except Exception as e:
                print_warning(f"Could not create config directory: {e}")

        # Check PATH
        self._check_path()

        # Show configuration hints
        if self.install_cli:
            self._show_config_hints()

        print(f"\n{Colors.GREEN}{Colors.BOLD}✓ Installation complete!{Colors.RESET}\n")

        if self.install_cli:
            print(f"Try: {Colors.BOLD}{self.cli_name} upload <file>{Colors.RESET}")
        if self.install_gui:
            print(f"Run GUI: {Colors.BOLD}{self.gui_name}{Colors.RESET}")

        return True

    def uninstall(self):
        """Uninstall the binaries"""
        targets = []
        if self.install_cli:
            targets.append("CLI")
        if self.install_gui:
            targets.append("GUI")

        print(
            f"\n{Colors.BOLD}Uninstalling COS {' and '.join(targets)}...{Colors.RESET}"
        )
        print(f"Mode: {'System' if self.system_mode else 'User'}\n")

        if not self.check_permissions():
            return False

        # Remove CLI
        if self.install_cli:
            if self.installed_cli.exists():
                try:
                    self.installed_cli.unlink()
                    print_success(f"Removed CLI: {self.installed_cli}")
                except Exception as e:
                    print_error(f"Failed to remove CLI binary: {e}")
                    return False
            else:
                print_warning(f"CLI binary not found: {self.installed_cli}")

        # Remove GUI
        if self.install_gui:
            if self.installed_gui.exists():
                try:
                    self.installed_gui.unlink()
                    print_success(f"Removed GUI: {self.installed_gui}")
                except Exception as e:
                    print_error(f"Failed to remove GUI binary: {e}")
                    return False
            else:
                print_warning(f"GUI binary not found: {self.installed_gui}")

            # Remove desktop entry (Linux only)
            if platform.system() == "Linux" and not self.system_mode:
                self._remove_desktop_entry()

        # Remove config directory if empty (Unix only)
        if platform.system() != "Windows" and hasattr(self, "config_dir"):
            if self.config_dir.exists():
                try:
                    if not any(self.config_dir.iterdir()):
                        self.config_dir.rmdir()
                        print_success(
                            f"Removed empty config directory: {self.config_dir}"
                        )
                    else:
                        print_info(
                            f"Config directory not empty, keeping: {self.config_dir}"
                        )
                except Exception as e:
                    print_warning(f"Could not remove config directory: {e}")

        # Remove installation directory if empty (Windows only)
        if platform.system() == "Windows" and self.install_dir.exists():
            try:
                if not any(self.install_dir.iterdir()):
                    self.install_dir.rmdir()
                    print_success(f"Removed empty installation directory")
            except Exception:
                pass

        print(
            f"\n{Colors.GREEN}{Colors.BOLD}✓ Uninstallation complete!{Colors.RESET}\n"
        )
        return True

    def _check_path(self):
        """Check if installation directory is in PATH"""
        path_env = os.environ.get("PATH", "")
        install_dir_str = str(self.install_dir)

        if install_dir_str not in path_env:
            print_warning(f"{self.install_dir} is not in PATH")

            if platform.system() == "Windows":
                print_info("Add to PATH manually or run:")
                print(f'  setx PATH "%PATH%;{install_dir_str}"')
            else:
                shell = os.environ.get("SHELL", "")
                if "zsh" in shell:
                    config_file = "~/.zshrc"
                elif "fish" in shell:
                    config_file = "~/.config/fish/config.fish"
                else:
                    config_file = "~/.bashrc"

                print_info(f"Add this to your {config_file}:")
                print(f'  export PATH="{install_dir_str}:$PATH"')

    def _show_config_hints(self):
        """Show configuration hints"""
        home = Path.home()
        config_file = home / ".cos-config.json"

        if not config_file.exists():
            print()
            print_warning("Configuration file not found")
            print_info("Create ~/.cos-config.json with your COS credentials:")
            print(
                """
{
  "secret_id": "your_secret_id",
  "secret_key": "your_secret_key",
  "bucket": "your_bucket_name",
  "region": "ap-shanghai"
}
            """.strip()
            )
            print()
            print_info("Or set environment variables:")
            print("  export COS_SECRET_ID=your_secret_id")
            print("  export COS_SECRET_KEY=your_secret_key")
            print("  export COS_BUCKET=your_bucket_name")
            print("  export COS_REGION=ap-shanghai")

    def _create_desktop_entry(self):
        """Create .desktop file for GUI (Linux only)"""
        try:
            desktop_dir = Path.home() / ".local" / "share" / "applications"
            desktop_dir.mkdir(parents=True, exist_ok=True)

            desktop_file = desktop_dir / "cos-gui.desktop"
            content = f"""[Desktop Entry]
Name=COS GUI
Comment=Tencent Cloud Object Storage GUI
Exec={self.installed_gui}
Icon=cloud
Terminal=false
Type=Application
Categories=Utility;
"""
            desktop_file.write_text(content)
            desktop_file.chmod(0o755)
            print_success(f"Created desktop entry: {desktop_file}")
        except Exception as e:
            print_warning(f"Could not create desktop entry: {e}")

    def _remove_desktop_entry(self):
        """Remove .desktop file (Linux only)"""
        try:
            desktop_file = (
                Path.home() / ".local" / "share" / "applications" / "cos-gui.desktop"
            )
            if desktop_file.exists():
                desktop_file.unlink()
                print_success(f"Removed desktop entry: {desktop_file}")
        except Exception as e:
            print_warning(f"Could not remove desktop entry: {e}")


def main():
    parser = argparse.ArgumentParser(
        description="COS CLI Installation Script",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  # Install to user directory
  python3 scripts/install.py --user

  # Install to system (requires sudo on Unix)
  sudo python3 scripts/install.py --system

  # Uninstall from user directory
  python3 scripts/install.py --uninstall --user

  # Uninstall from system
  sudo python3 scripts/install.py --uninstall --system
        """,
    )

    parser.add_argument(
        "--system",
        action="store_true",
        help="Install to system directory (requires admin/sudo)",
    )

    parser.add_argument(
        "--user", action="store_true", help="Install to user directory (default)"
    )

    parser.add_argument(
        "--uninstall", action="store_true", help="Uninstall instead of install"
    )

    parser.add_argument("--cli", action="store_true", help="Install/uninstall CLI")

    parser.add_argument("--gui", action="store_true", help="Install/uninstall GUI")

    args = parser.parse_args()

    # Default to user installation if neither specified
    system_mode = args.system
    if not args.system and not args.user:
        system_mode = False

    # Default to CLI if neither specified
    install_cli = args.cli
    install_gui = args.gui
    if not args.cli and not args.gui:
        install_cli = True
        install_gui = False

    installer = Installer(
        system_mode=system_mode, install_cli=install_cli, install_gui=install_gui
    )

    try:
        if args.uninstall:
            success = installer.uninstall()
        else:
            success = installer.install()

        sys.exit(0 if success else 1)

    except KeyboardInterrupt:
        print("\n\nInstallation cancelled by user")
        sys.exit(1)
    except Exception as e:
        print_error(f"Unexpected error: {e}")
        sys.exit(1)


if __name__ == "__main__":
    main()
